﻿using System;
using System.Text;
using TI_BLE_HCI_ClientLib.BaseEntities;
using TI_BLE_HCI_ClientLib.GenericHCIEntities;
using TI_BLE_HCI_ClientLib.HCIBaseEntities;

namespace TI_BLE_HCI_ClientLib.HCICommands
{
    public class HCICommand_GATT_Read_By_Group_Type_Response : HCIVendorSpecificCommand
    {
        private const byte CMD = 0x11;

        public HCICommand_GATT_Read_By_Group_Type_Response(ushort connHandle, byte length, byte[] attrData)
            : base(HCIVendorSpecificCommandCSG.ATT, CMD)
        {
            var pars = new BaseEntityParameter[3];

            pars[0] = new WordParameter(connHandle);
            pars[1] = new ByteParameter(length);
            pars[2] = new ByteArrayParameter(attrData);

            base.addParameters(pars);
        }

        public HCICommand_GATT_Read_By_Group_Type_Response(ushort connHandle, AttributeGroupData[] attrGroupDataArray)
            : this(connHandle, getAttributeGroupLength(attrGroupDataArray), getAttributeGroupArrayData(attrGroupDataArray))
        { }


        static byte getAttributeGroupLength(AttributeGroupData[] attrGroupDataArray)
        {
            if (attrGroupDataArray == null || attrGroupDataArray.Length == 0) return 0;

            byte len = attrGroupDataArray[0].Length;

            for (int i = 0; i < attrGroupDataArray.Length; i++)
            {
                if(attrGroupDataArray[i].Length!=len)
                {
                    throw new ArgumentException("AttributeGroupDataArray item length is not the same for each item");
                }
            }

            return len;
        }

        static byte[] getAttributeGroupArrayData(AttributeGroupData[] attrGroupDataArray)
        {
            if (attrGroupDataArray == null || attrGroupDataArray.Length == 0) return new byte[0];

            byte groupLen = attrGroupDataArray[0].Length;

            var buf = new byte[attrGroupDataArray.Length * groupLen];

            for(int i=0;i<attrGroupDataArray.Length;i++)
            {
                Array.Copy(attrGroupDataArray[i].ToByteArray(), 0, buf, i * groupLen, groupLen);
            }

            return buf;
        }

        public class AttributeGroupData
        {
            ushort _startGroupHandle;
            ushort _endGroupHandle;

            byte[] _attributeValue;

            public AttributeGroupData(ushort startGroupHandle, ushort endGroupHandle, byte[] attributeValue)
            {
                _startGroupHandle = startGroupHandle;
                _endGroupHandle = endGroupHandle;
                _attributeValue = attributeValue;
            }

            public AttributeGroupData(ushort startGroupHandle, ushort endGroupHandle, ushort attributeValue)
                : this(startGroupHandle, endGroupHandle, new byte[] { (byte)(attributeValue & 0xFF), (byte)((attributeValue >> 8) & 0xFF) })
            {
            }

            public byte Length
            {
                get
                {
                    return (byte)(_attributeValue.Length + 4);
                }
            }

            public byte[] ToByteArray()
            {
                var buf = new byte[4 + _attributeValue.Length];

                buf[0] = (byte)(_startGroupHandle & 0xFF);
                buf[1] = (byte)((_startGroupHandle >> 8) & 0xFF);

                buf[2] = (byte)(_endGroupHandle & 0xFF);
                buf[3] = (byte)((_endGroupHandle >> 8) & 0xFF);

                Array.Copy(_attributeValue, 0, buf, 4, _attributeValue.Length);

                return buf;
            }
        }
    }
}
